﻿using System;
using System.Drawing;
using System.Net.NetworkInformation;
using System.Threading;
using System.Windows.Forms;
using BrightIdeasSoftware;
using DevExpress.XtraEditors;
using LIK.NetworkTools;
using LIK.WakeOnLan.Code;
using LIK.WakeOnLan.Network;
using LIK.WakeOnLan.Properties;
using Timer = System.Windows.Forms.Timer;

namespace LIK.WakeOnLan.Forms
{
    public partial class FormNetworkScanner : XtraForm
    {
        private delegate void FormUpdateDelegate();

        private Timer delayRunTimer;

        private Thread scaningThread;

        internal NetworkClient NetworkClient
        {
            get { return lstNetworkClients.SelectedObject as NetworkClient; }
        }

        public void AsScanerOnly()
        {
            btnAdd.Image = Resources.add_blue;
            btnAdd.ToolTip = "Add Selected Client To Quick List";
            btnAdd.Text = "Add";
        }

        public FormNetworkScanner()
        {
            InitializeComponent();
            //pictureEditBusy.Parent = lstNetworkClients;
            this.Controls.Remove(btnNewNetworkScan);
            this.Controls.Remove(btnCleanUpAll); 
            FormPopup.SetParent(this);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.olvColumnFavStatus.AspectGetter = row => ((NetworkClient) row).FavStatus;
            this.olvColumnFavStatus.Renderer = new MappedImageRenderer(new Object[] {
                NetworkClientFavoritesStatus.In, new Bitmap(imageList.Images[3]),
                NetworkClientFavoritesStatus.None, new Bitmap(imageList.Images[4])
            });

            lstNetworkClients.Items.Clear();
            lstNetworkClients.Objects = NetworkClients.Instance;


            this.lstNetworkClients.CellEditStarting += (s, evt) =>
            {
                if (evt.Column.Text != olvColumnFavStatus.Text)
                    return;
                NetworkClient networkClient = (NetworkClient)evt.RowObject;
                if (networkClient.FavStatus == NetworkClientFavoritesStatus.In)
                {
                    networkClient.FavStatus = NetworkClientFavoritesStatus.None;
                }
                else
                {
                    networkClient.FavStatus = NetworkClientFavoritesStatus.In;
                }
                evt.Cancel = true;
                ((ObjectListView)s).RefreshItem(evt.ListViewItem);
            };
            //this.lstNetworkClients.CellEditFinishing += (s, evt) =>
            //{
            //    // We only want to mess with the Cooking Skill column
            //    if (evt.Column.Text != olvColumnFavStatus.Name)
            //        return;

            //    ((ObjectListView)s).RefreshItem(evt.ListViewItem);

            //    evt.Cancel = true;
            //};
            this.lstNetworkClients.Enabled = true;
            this.progressPanel.Visible = false;
            if (Settings.Default.ScanOnStartupOn && NetworkClients.FirstRun)
            {
                this.PrepairGuiForScan();
                delayRunTimer = new Timer {Interval = 500};
                delayRunTimer.Start();
                delayRunTimer.Tick += (s, arg) =>
                {
                    delayRunTimer.Stop();
                    delayRunTimer.Dispose();
                    ScanNetwork(null);
                };
            }
            else
            {
                lstNetworkClients.Refresh();
            }
            NetworkClients.FirstRun = false;
        }

        private void listViewComplex_CellEditFinishing(object sender, CellEditEventArgs e)
        {
            // We only want to mess with the Cooking Skill column
            if (e.Column.Text != olvColumnFavStatus.Name)
                return;

            // ObjectListView will automatically dispose of the control we created.
            // If we didn't want that (e.g. if the control was expensive to create and we
            // wanted to cache and reuse it), we would set e.AutoDispose = false

            // Any updating will have been down in the SelectedIndexChanged event handler
            // Here we simply make the list redraw the involved ListViewItem
            ((ObjectListView)sender).RefreshItem(e.ListViewItem);

            // We have updated the model object, so we cancel the auto update
            e.Cancel = true;
        }

        private void listBoxControlClients_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.simpleButtonAdd_Click(null, null);
        }

        private void mnuAddToFavorites_Click(object sender, EventArgs e)
        {
            this.simpleButtonAdd_Click(null, null);
        }

        private void simpleButtonAdd_Click(object sender, EventArgs e)
        {
            if (lstNetworkClients.SelectedObject != null)
            {
                if (this.NetworkClient != null && !this.NetworkClient.MacAddress.Equals(IpHelper.NotFound))
                {
                    this.DialogResult = DialogResult.OK;
                    return;
                }
            }
            this.DialogResult = DialogResult.None;
        }

        private void btnNewNetworkScan_Click(object sender, EventArgs e)
        {
            string strNetworkIpAddress;
            this.TopMost = true;
            using (FormInputIp formInputIp = new FormInputIp())
            {
                formInputIp.IpAddress = Settings.Default.LastUsedNetworkIpAddress;
                this.TopMost = false;
                formInputIp.TopMost = true;
                formInputIp.Focus();
                formInputIp.TopMost = false;
                if (formInputIp.ShowDialog(this) != DialogResult.OK) return;
                strNetworkIpAddress = formInputIp.IpAddress;
                Settings.Default.LastUsedNetworkIpAddress = formInputIp.IpAddress;
                 Settings.Default.Save();
            }
         
            this.PrepairGuiForScan();
            scaningThread = new Thread(new ParameterizedThreadStart(ScanNetwork)) { Priority = ThreadPriority.AboveNormal };
            scaningThread.Start(strNetworkIpAddress);
        }

        private void btnScan_Click_1(object sender, EventArgs e)
        {
            this.PrepairGuiForScan();
            scaningThread = new Thread(ScanNetwork) { Priority = ThreadPriority.AboveNormal };
            scaningThread.Start();
        }

        private void PrepairGuiForScan()
        {
            this.btnScan.Enabled = false;
            this.progressPanel.Visible = true;
            this.lstNetworkClients.Enabled = false;
            this.progressPanel.Caption = "Scaning IP Addresses";
            this.lstNetworkClients.Objects = (NetworkClients.Instance);
            this.Refresh();
            this.Cursor = Cursors.WaitCursor;
        }

        private void ScanNetwork(object strNetworkIpAddress)
        {
            if (strNetworkIpAddress == null)
            {
                NetworkClients.LocalNetworkScan();
            }
            else
            {
                NetworkClients.NetworkScan(strNetworkIpAddress.ToString());
            }
            this.InterimThreadState();
            if (chckbResolveClientNames.Checked)
            {
                NetworkClients.ResolveNames();
            }
            this.ThreadCompleted();
        }

        private void InterimThreadState()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new FormUpdateDelegate(InterimThreadState), new object[0]);
            }
            else
            {
                lstNetworkClients.Objects = (NetworkClients.Instance);
                this.progressPanel.Caption = "Resolving Host Names";
                this.Refresh();
            }
        }

        private void ThreadCompleted()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new FormUpdateDelegate(ThreadCompleted), new object[0]);
            }
            else
            {
                this.lstNetworkClients.Objects = (NetworkClients.Instance);
                this.Refresh();
                this.Cursor = Cursors.Default;
                this.btnScan.Enabled = true;
                this.progressPanel.Visible = false;
                this.lstNetworkClients.Enabled = true;
            }
        }

        private void cmnuRemoveClient_Click(object sender, EventArgs e)
        {
            var nclnt = lstNetworkClients.SelectedObject as NetworkClient;
            if (nclnt != null)
            {
                if (XtraMessageBox.Show("Would you like to remove selected client from the list?", "Network Clients", 
                    MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    return;
                }
                NetworkClients.Instance.Remove(nclnt);
                this.lstNetworkClients.Objects = (NetworkClients.Instance);
                this.Refresh();
            }
        }

        private void cmnuCopyInfo_Click(object sender, EventArgs e)
        {
            var nclnt = lstNetworkClients.SelectedObject as NetworkClient;
            if (nclnt != null)
            {
                Clipboard.SetText(nclnt.ToString());
            }
        }

        private void btnShutDown_Click(object sender, EventArgs e)
        {
            NetworkClient nclnt = lstNetworkClients.SelectedObject as NetworkClient;
            if (nclnt == null) // || nclnt.Status != NetworkClientStatus.On)
            {
                XtraMessageBox.Show("Select network client first");
                return;
            }
            if (!nclnt.IsOnline())
            {
                XtraMessageBox.Show("Network client is offline");
                return;
            }
            using (FormShutDown frmShutDown = new FormShutDown())
            {
                frmShutDown.HostName = nclnt.HostName;
                frmShutDown.ShowDialog(this);
            }
        }

        private void btnCleanUpList_Click(object sender, EventArgs e)
        {
            this.CleanUpClients(true);
        }

        private void btnCleanUpAll_Click(object sender, EventArgs e)
        {
            this.CleanUpClients(false);
        }

        private void CleanUpClients(bool exludingFavorites)
        {
            if (NetworkClients.Instance.Count == 0)
            {
                return;
            }
            string message = exludingFavorites
                ? "Would you like to keep only Favorites in list?" 
                : "Would you like to reset the list?";
            if (XtraMessageBox.Show(message, "Network Clients", MessageBoxButtons.YesNo) !=
                DialogResult.Yes)
            {
                return;
            }
            this.lstNetworkClients.Objects = exludingFavorites 
                ? NetworkClients.Instance.ClearAllExcludinFavorites() 
                : NetworkClients.Instance.ClearAll();
            this.Refresh();
        }

        private void btnScan_ShowDropDownControl(object sender, ShowDropDownControlEventArgs e)
        {
            FormPopup.ShowPopup(btnNewNetworkScan, btnScan);
        }

        private void btnCleanUpNotFav_ShowDropDownControl(object sender, ShowDropDownControlEventArgs e)
        {
            FormPopup.ShowPopup(btnCleanUpAll, btnCleanUpNotFav);
        }

        private void cmnuPing_Click(object sender, EventArgs e)
        {
            var nclnt = lstNetworkClients.SelectedObject as NetworkClient;
            if (nclnt == null)
            {
                XtraMessageBox.Show("Select network client first");
                return;
            }
            this.Cursor = Cursors.WaitCursor;
            NetworkClients.PingSingle(nclnt.IpAddress);
            this.Refresh();
            this.Cursor = Cursors.Default;
        }

        private void cmnuWakeUp_Click(object sender, EventArgs e)
        {
            var networkPresent = NetworkInterface.GetIsNetworkAvailable();
            if (!networkPresent)
            {
                XtraMessageBox.Show("Network is not available");
                return;
            }
            var nclnt = lstNetworkClients.SelectedObject as NetworkClient;
            if (nclnt == null)
            {
                XtraMessageBox.Show("Select network client first");
                return;
            }
            if (nclnt.IsOnline())
            {
                XtraMessageBox.Show("Network client is online");
                return;
            }
            this.lstNetworkClients.Enabled = false;
            progressPanel.Visible = true;
            progressPanel.Refresh();
            Application.DoEvents();
            WolCommand.SendWakUpOnLanMessage(nclnt);
            Thread.Sleep(250);
            progressPanel.Visible = false;
            this.lstNetworkClients.Enabled = true;
        }




















    }
}
